#library(MASS)

library(ggplot2)
RStudio Community is a great place to get help: https://community.rstudio.com/c/tidyverse
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(bio3d)
library(tidyverse)
── Attaching core tidyverse packages ────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ lubridate 1.9.3     ✔ tibble    3.2.1
✔ purrr     1.0.2     ✔ tidyr     1.3.0
✔ readr     2.1.4     ── Conflicts ──────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(colorspace)
library(cowplot)

Attaching package: ‘cowplot’

The following object is masked from ‘package:lubridate’:

    stamp
library(ggpubr)

Attaching package: ‘ggpubr’

The following object is masked from ‘package:cowplot’:

    get_legend
library(patchwork)

Attaching package: ‘patchwork’

The following object is masked from ‘package:cowplot’:

    align_plots
source("dms_analysis_utilities.R")

#source("oct1_dms_read_enrich.R")

Read score files

# Enrich2 score files
oct1_combined_scores_file ="../data/oct1_combined_scores.csv"
oct1_combined_scores <- read_csv(oct1_combined_scores_file)
Rows: 11573 Columns: 28── Column specification ──────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (4): hgvs, mutation_type, variants, wt_pos
dbl (23): SM73_0_SE, SM73_0_epsilon, SM73_1_SE, SM73_1_epsilon, GFP_SE, GFP_epsilon, pos, len, SM73_0_...
lgl  (1): is.wt
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
oct1_combined_scores <- oct1_combined_scores %>% mutate(pos = as.integer(pos),
                                                        len = as.integer(len))
oct1_wt = "MPTVDDILEQVGESGWFQKQAFLILCLLSAAFAPICVGIVFLGFTPDHHCQSPGVAELSQRCGWSPAEELNYTVPGLGPAGEAFLGQCRRYEVDWNQSALSCVDPLASLATNRSHLPLGPCQDGWVYDTPGSSIVTEFNLVCADSWKLDLFQSCLNAGFLFGSLGVGYFADRFGRKLCLLGTVLVNAVSGVLMAFSPNYMSMLLFRLLQGLVSKGNWMAGYTLITEFVGSGSRRTVAIMYQMAFTVGLVALTGLAYALPHWRWLQLAVSLPTFLFLLYYWCVPESPRWLLSQKRNTEAIKIMDHIAQKNGKLPPADLKMLSLEEDVTEKLSPSFADLFRTPRLRKRTFILMYLWFTDSVLYQGLILHMGATSGNLYLDFLYSALVEIPGAFIALITIDRVGRIYPMAMSNLLAGAACLVMIFISPDLHWLNIIIMCVGRMGITIAIQMICLVNAELYPTFVRNLGVMVCSSLCDIGGIITPFIVFRLREVWQALPLILFAVLGLLAAGVTLLLPETKGVALPETMKDAENLGRKAKPKENTIYLKVQTSEPSGT"

Plot the correlation between the two scores and quantify it.

Plots all (in black) and synonymous (in red) variants, regression line, as well as correlations.

score_plot <- ggplot(oct1_combined_scores %>% filter(mutation_type != "X"),
                     aes(y = SM73_1_score, x = GFP_score)) +
  geom_point(alpha = 0.2) +
  ggtitle('Correlation between function and abundance scores') +
  stat_cor(method = "spearman", label.x = -5.5, label.y = -1, color = 'black',
           cor.coef.name = "rho") +
  geom_smooth(method='lm', se = TRUE) +
  geom_point(data = oct1_combined_scores %>% filter(mutation_type == "S"),
             color = 'red', alpha = 0.5) +
  stat_cor(data = oct1_combined_scores %>% filter(mutation_type == "S"),
           method = "spearman", label.x = -5.5, label.y = -1.5, color = 'red',
           cor.coef.name = "rho") +
  geom_smooth(data = oct1_combined_scores %>% filter(mutation_type == "S"),
              method='lm', se = TRUE) +
  ylab("Cytotoxicity score") +
  xlab("Abundance score") +
  theme_classic() 

score_plot

ggsave("output/score_correlations.png", width = 5, height = 4, score_plot)
ggsave("output/score_correlations.pdf", width = 5, height = 4, score_plot)

NA
NA

Investigate the correlation between the baseline counts and abundance scores

getwd()
[1] "/Users/bartleby/Desktop/Projects/OCT1/OCT1_DMS/Figures"
oct1_counts_1SM73_T0_R1_file ="../data/counts/OCT1_full/Cy1a.csv"
oct1_counts_1SM73_T0_R2_file ="../data/counts/OCT1_full/Cy1b.csv"
oct1_counts_1SM73_T0_R3_file ="../data/counts/OCT1_full/C.csv"

oct1_counts_1SM73_T0_R1 <- read_delim(oct1_counts_1SM73_T0_R1_file, col_select = !1)
New names:Rows: 11572 Columns: 10── Column specification ──────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): mutation_type, name, codon, mutation, hgvs
dbl (5): count, pos, chunk_pos, chunk, length
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
oct1_counts_1SM73_T0_R2 <- read_delim(oct1_counts_1SM73_T0_R2_file, col_select = !1)
New names:Rows: 11572 Columns: 10── Column specification ──────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): mutation_type, name, codon, mutation, hgvs
dbl (5): count, pos, chunk_pos, chunk, length
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
oct1_counts_1SM73_T0_R3 <- read_delim(oct1_counts_1SM73_T0_R3_file, col_select = !1)
New names:Rows: 11572 Columns: 10── Column specification ──────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): mutation_type, name, codon, mutation, hgvs
dbl (5): count, pos, chunk_pos, chunk, length
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
oct1_scores_counts <- full_join(oct1_counts_1SM73_T0_R1, oct1_combined_scores)
Joining with `by = join_by(pos, mutation_type, hgvs)`
score_baseline_plot_abundance <- ggplot(oct1_scores_counts %>% filter(mutation_type != "X"),
                     aes(y = count, x = GFP_score)) +
  ggtitle('Baseline library count and abundance score correlation') +
  geom_point(alpha = 0.2) +
  stat_cor(method = "spearman", color = 'black', cor.coef.name = "rho") +
  geom_smooth(method='lm', se = TRUE) +
  ylab("Baseline count") +
  xlab("Abundance score") +
  theme_classic() 

score_baseline_plot_abundance

ggsave("output/score_baseline_plot_abundance.png", width = 5, height = 4, score_baseline_plot_abundance)
ggsave("output/score_baseline_plot_abundance.pdf", width = 5, height = 4, score_baseline_plot_abundance)



score_baseline_plot_sm73 <- ggplot(oct1_scores_counts %>% filter(mutation_type != "X"),
                     aes(y = count, x = SM73_1_score)) +
  ggtitle('Baseline library count and function score correlation') +
  geom_point(alpha = 0.2) +
  stat_cor(method = "spearman", color = 'black', cor.coef.name = "rho") +
  geom_smooth(method='lm', se = TRUE) +
  ylab("Baseline count") +
  xlab("Abundance score") +
  theme_classic() 

score_baseline_plot_sm73

ggsave("output/score_baseline_plot_sm73.png", width = 5, height = 4, score_baseline_plot_sm73)
ggsave("output/score_baseline_plot_sm73.pdf", width = 5, height = 4, score_baseline_plot_sm73)


score_baseline_plots <- score_baseline_plot_abundance + score_baseline_plot_sm73 + 
                    plot_layout(ncol = 2, nrow = 1, widths = c(5, 5), heights = c(4))

score_baseline_plots

ggsave("output/score_baseline_plots.png", width = 8, height = 4, score_baseline_plots)
ggsave("output/score_baseline_plots.pdf", width = 8, height = 4, score_baseline_plots)

NA
NA

volcano_GFP <- ggplot(oct1_combined_scores %>% filter(mutation_type != "X"),
                     aes(y = GFP_SE, x = GFP_score)) +
  ggtitle('Baseline library count and function score correlation') +
  geom_point(alpha = 0.2) +
  ylab("Abundance SE") +
  xlab("Abundance score") +
  theme_classic() 

volcano_GFP

volcano_SM73 <- ggplot(oct1_combined_scores %>% filter(mutation_type != "X"),
                     aes(y = SM73_1_SE, x = SM73_1_score)) +
  ggtitle('Baseline library count and function score correlation') +
  geom_point(alpha = 0.2) +
  ylab("Function SE") +
  xlab("Function score") +
  theme_classic() 

volcano_SM73
oct1_AF_missense_file ="../data/AlphaMissense_aa_substitutions_O15245.tsv"
oct1_AF_missense <- read_delim(oct1_AF_missense_file, delim = '\t',
                               col_names = c('uniprot_id', 'protein_variant',
                                             'am_pathogenicity', 'am_class')) %>%
  mutate(protein_variant = paste('p.(', protein_variant, ')', sep = ''))
Rows: 10526 Columns: 4── Column specification ──────────────────────────────────────────────────────────────────────────────────────────
Delimiter: "\t"
chr (3): uniprot_id, protein_variant, am_class
dbl (1): am_pathogenicity
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
oct1_AF_missense <- oct1_AF_missense %>% mutate(pos = as.numeric(str_match(protein_variant, "^p.\\([A-Z]([0-9]+)[dA-Z_]\\)")[,2]))


oct1_AF_missense_scores <- full_join(oct1_AF_missense, oct1_scores, by = c("protein_variant" = "hgvs"))

oct1_AF_missense_scores <- oct1_AF_missense_scores %>% mutate(pos = as.numeric(str_match(protein_variant, "^p.\\([A-Z]([0-9]+)[dA-Z_]\\)")[,2]))

oct1_AF_missense_scores <- oct1_AF_missense_scores %>% mutate(variants = str_match(protein_variant, "^p.\\([A-Z][0-9]+([dA-Z_])\\)")[,2])

AF_correlation <- ggplot(oct1_AF_missense_scores %>% filter(mutation_type != "X"),
                     aes(y = am_pathogenicity, x = SM73_1_score)) +
  geom_point(alpha = 0.1, color = 'blue') +
  ylab("AlphaMissense pathogenicity score") +
  xlab("Cytotoxicity score") +
  stat_cor(method = "spearman", label.x = 1, label.y = 0.1, color = 'black',
           cor.coef.name = "rho") +
  geom_hline(yintercept = 0.34, linetype = 2) + 
  geom_hline(yintercept = 0.564, linetype = 2) + 
  geom_vline(xintercept = 0.6798075, linetype = 2) + 
  geom_vline(xintercept = -0.8376936, linetype = 2) + 
  theme_classic() 

AF_correlation

ggsave("output/AF_correlation_sm73.png", width = 5, height = 2, AF_correlation)



AF_correlation_GFP <- ggplot(oct1_AF_missense_scores %>% filter(mutation_type != "X"),
                     aes(y = am_pathogenicity, x = GFP_score)) +
  geom_point(alpha = 0.1, color = 'red') +
  ylab("AlphaMissense pathogenicity score") +
  xlab("Abundance score") +
  stat_cor(method = "spearman", label.x = -5, label.y = 0.1, color = 'black',
           cor.coef.name = "rho") +
  geom_hline(yintercept = 0.34, linetype = 2) + 
  geom_hline(yintercept = 0.564, linetype = 2) + 
  geom_vline(xintercept = 0.7967691, linetype = 2) + 
  geom_vline(xintercept = -0.7207321, linetype = 2) + 
  theme_classic() 

AF_correlation_GFP

ggsave("output/AF_correlation_GFP.png", width = 5, height = 2, AF_correlation_GFP)



folding_plots <- AF_correlation + AF_correlation_GFP + 
                    plot_layout(ncol = 2, nrow = 1, widths = c(5, 5), heights = c(2))

folding_plots

ggsave("output/AF_correlation_plots.png", width = 10, height = 4, folding_plots)
ggsave("output/AF_correlation_plots.pdf", width = 10, height = 4, folding_plots)

NA
NA
NA

order <- c('D_1', 'H', 'K', 'R', 'D', 'E',
          'C', 'M', 'N', 'Q', 'S', 'T', 'A', 'I', 'L', 'V', 'W', 'F',
          'Y', 'G', 'P')

names <- c('Del', 'H', 'K', 'R', 'D', 'E',
          'C', 'M', 'N', 'Q', 'S', 'T', 'A', 'I', 'L', 'V', 'W', 'F',
          'Y', 'G', 'P')

oct1_wt = "MPTVDDILEQVGESGWFQKQAFLILCLLSAAFAPICVGIVFLGFTPDHHCQSPGVAELSQRCGWSPAEELNYTVPGLGPAGEAFLGQCRRYEVDWNQSALSCVDPLASLATNRSHLPLGPCQDGWVYDTPGSSIVTEFNLVCADSWKLDLFQSCLNAGFLFGSLGVGYFADRFGRKLCLLGTVLVNAVSGVLMAFSPNYMSMLLFRLLQGLVSKGNWMAGYTLITEFVGSGSRRTVAIMYQMAFTVGLVALTGLAYALPHWRWLQLAVSLPTFLFLLYYWCVPESPRWLLSQKRNTEAIKIMDHIAQKNGKLPPADLKMLSLEEDVTEKLSPSFADLFRTPRLRKRTFILMYLWFTDSVLYQGLILHMGATSGNLYLDFLYSALVEIPGAFIALITIDRVGRIYPMAMSNLLAGAACLVMIFISPDLHWLNIIIMCVGRMGITIAIQMICLVNAELYPTFVRNLGVMVCSSLCDIGGIITPFIVFRLREVWQALPLILFAVLGLLAAGVTLLLPETKGVALPETMKDAENLGRKAKPKENTIYLKVQTSEPSGT"

print_heatmap(oct1_combined_scores, GFP_score, oct1_wt)

variance_plot <- ggplot(data = oct1_AF_missense %>% group_by(pos) %>%
    summarise(cv = sd(am_pathogenicity, na.rm=T)/abs(mean(am_pathogenicity, na.rm=T))), aes(x = cv)) +
  geom_density() +
  geom_density(data = oct1_combined_scores %>% group_by(pos) %>%
    summarise(cv = sd(SM73_1_score, na.rm=T)/abs(mean(SM73_1_score, na.rm=T))), aes(x = cv), color = "blue", linetype = 2) +
  geom_density(data = oct1_combined_scores %>% group_by(pos) %>%
    summarise(cv = sd(GFP_score, na.rm=T)/abs(mean(GFP_score, na.rm=T))), aes(x = cv), color = "red", linetype = 2) +
  xlim(c(0, 10)) +
  ylab("Density") +
  xlab("Coefficient of variation") +
  theme_classic()

variance_plot

ggsave("output/AF_CV_plot.png", width = 10, height = 5, variance_plot)
ggsave("output/AF_CV_plot.pdf", width = 10, height = 5, variance_plot)

Write the scores as 3 letter HGVS AAs to submit to MAVE db


write.csv(oct1_combined_scores %>% ungroup() %>% rowwise() %>% mutate(hgvs_3 = convert_1AA_hgvs(hgvs)), "../data/MAVE_db_scores.csv")

```

LS0tCnRpdGxlOiAiUG9zdC1yZXZpZXcgYW5hbHlzaXMiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKYGBge3J9CiNsaWJyYXJ5KE1BU1MpCgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoYmlvM2QpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGNvbG9yc3BhY2UpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkocGF0Y2h3b3JrKQoKc291cmNlKCJkbXNfYW5hbHlzaXNfdXRpbGl0aWVzLlIiKQoKI3NvdXJjZSgib2N0MV9kbXNfcmVhZF9lbnJpY2guUiIpCgpgYGAKClJlYWQgc2NvcmUgZmlsZXMKCmBgYHtyfQojIEVucmljaDIgc2NvcmUgZmlsZXMKb2N0MV9jb21iaW5lZF9zY29yZXNfZmlsZSA9Ii4uL2RhdGEvb2N0MV9jb21iaW5lZF9zY29yZXMuY3N2IgpvY3QxX2NvbWJpbmVkX3Njb3JlcyA8LSByZWFkX2NzdihvY3QxX2NvbWJpbmVkX3Njb3Jlc19maWxlKQoKb2N0MV9jb21iaW5lZF9zY29yZXMgPC0gb2N0MV9jb21iaW5lZF9zY29yZXMgJT4lIG11dGF0ZShwb3MgPSBhcy5pbnRlZ2VyKHBvcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuID0gYXMuaW50ZWdlcihsZW4pKQoKYGBgCgpgYGB7cn0Kb2N0MV93dCA9ICJNUFRWRERJTEVRVkdFU0dXRlFLUUFGTElMQ0xMU0FBRkFQSUNWR0lWRkxHRlRQREhIQ1FTUEdWQUVMU1FSQ0dXU1BBRUVMTllUVlBHTEdQQUdFQUZMR1FDUlJZRVZEV05RU0FMU0NWRFBMQVNMQVROUlNITFBMR1BDUURHV1ZZRFRQR1NTSVZURUZOTFZDQURTV0tMRExGUVNDTE5BR0ZMRkdTTEdWR1lGQURSRkdSS0xDTExHVFZMVk5BVlNHVkxNQUZTUE5ZTVNNTExGUkxMUUdMVlNLR05XTUFHWVRMSVRFRlZHU0dTUlJUVkFJTVlRTUFGVFZHTFZBTFRHTEFZQUxQSFdSV0xRTEFWU0xQVEZMRkxMWVlXQ1ZQRVNQUldMTFNRS1JOVEVBSUtJTURISUFRS05HS0xQUEFETEtNTFNMRUVEVlRFS0xTUFNGQURMRlJUUFJMUktSVEZJTE1ZTFdGVERTVkxZUUdMSUxITUdBVFNHTkxZTERGTFlTQUxWRUlQR0FGSUFMSVRJRFJWR1JJWVBNQU1TTkxMQUdBQUNMVk1JRklTUERMSFdMTklJSU1DVkdSTUdJVElBSVFNSUNMVk5BRUxZUFRGVlJOTEdWTVZDU1NMQ0RJR0dJSVRQRklWRlJMUkVWV1FBTFBMSUxGQVZMR0xMQUFHVlRMTExQRVRLR1ZBTFBFVE1LREFFTkxHUktBS1BLRU5USVlMS1ZRVFNFUFNHVCIKCmBgYAoKUGxvdCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgdHdvIHNjb3JlcyBhbmQgcXVhbnRpZnkgaXQuCgpQbG90cyBhbGwgKGluIGJsYWNrKSBhbmQgc3lub255bW91cyAoaW4gcmVkKSB2YXJpYW50cywgcmVncmVzc2lvbiBsaW5lLCBhcyB3ZWxsIGFzIGNvcnJlbGF0aW9ucy4KCmBgYHtyfQpzY29yZV9wbG90IDwtIGdncGxvdChvY3QxX2NvbWJpbmVkX3Njb3JlcyAlPiUgZmlsdGVyKG11dGF0aW9uX3R5cGUgIT0gIlgiKSwKICAgICAgICAgICAgICAgICAgICAgYWVzKHkgPSBTTTczXzFfc2NvcmUsIHggPSBHRlBfc2NvcmUpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMikgKwogIGdndGl0bGUoJ0NvcnJlbGF0aW9uIGJldHdlZW4gZnVuY3Rpb24gYW5kIGFidW5kYW5jZSBzY29yZXMnKSArCiAgc3RhdF9jb3IobWV0aG9kID0gInNwZWFybWFuIiwgbGFiZWwueCA9IC01LjUsIGxhYmVsLnkgPSAtMSwgY29sb3IgPSAnYmxhY2snLAogICAgICAgICAgIGNvci5jb2VmLm5hbWUgPSAicmhvIikgKwogIGdlb21fc21vb3RoKG1ldGhvZD0nbG0nLCBzZSA9IFRSVUUpICsKICBnZW9tX3BvaW50KGRhdGEgPSBvY3QxX2NvbWJpbmVkX3Njb3JlcyAlPiUgZmlsdGVyKG11dGF0aW9uX3R5cGUgPT0gIlMiKSwKICAgICAgICAgICAgIGNvbG9yID0gJ3JlZCcsIGFscGhhID0gMC41KSArCiAgc3RhdF9jb3IoZGF0YSA9IG9jdDFfY29tYmluZWRfc2NvcmVzICU+JSBmaWx0ZXIobXV0YXRpb25fdHlwZSA9PSAiUyIpLAogICAgICAgICAgIG1ldGhvZCA9ICJzcGVhcm1hbiIsIGxhYmVsLnggPSAtNS41LCBsYWJlbC55ID0gLTEuNSwgY29sb3IgPSAncmVkJywKICAgICAgICAgICBjb3IuY29lZi5uYW1lID0gInJobyIpICsKICBnZW9tX3Ntb290aChkYXRhID0gb2N0MV9jb21iaW5lZF9zY29yZXMgJT4lIGZpbHRlcihtdXRhdGlvbl90eXBlID09ICJTIiksCiAgICAgICAgICAgICAgbWV0aG9kPSdsbScsIHNlID0gVFJVRSkgKwogIHlsYWIoIkN5dG90b3hpY2l0eSBzY29yZSIpICsKICB4bGFiKCJBYnVuZGFuY2Ugc2NvcmUiKSArCiAgdGhlbWVfY2xhc3NpYygpIAoKc2NvcmVfcGxvdAoKZ2dzYXZlKCJvdXRwdXQvc2NvcmVfY29ycmVsYXRpb25zLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gNCwgc2NvcmVfcGxvdCkKZ2dzYXZlKCJvdXRwdXQvc2NvcmVfY29ycmVsYXRpb25zLnBkZiIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gNCwgc2NvcmVfcGxvdCkKCgpgYGAKCkludmVzdGlnYXRlIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBiYXNlbGluZSBjb3VudHMgYW5kIGFidW5kYW5jZSBzY29yZXMKCmBgYHtyfQpnZXR3ZCgpCm9jdDFfY291bnRzXzFTTTczX1QwX1IxX2ZpbGUgPSIuLi9kYXRhL2NvdW50cy9PQ1QxX2Z1bGwvQ3kxYS5jc3YiCm9jdDFfY291bnRzXzFTTTczX1QwX1IyX2ZpbGUgPSIuLi9kYXRhL2NvdW50cy9PQ1QxX2Z1bGwvQ3kxYi5jc3YiCm9jdDFfY291bnRzXzFTTTczX1QwX1IzX2ZpbGUgPSIuLi9kYXRhL2NvdW50cy9PQ1QxX2Z1bGwvQy5jc3YiCgpvY3QxX2NvdW50c18xU003M19UMF9SMSA8LSByZWFkX2RlbGltKG9jdDFfY291bnRzXzFTTTczX1QwX1IxX2ZpbGUsIGNvbF9zZWxlY3QgPSAhMSkKb2N0MV9jb3VudHNfMVNNNzNfVDBfUjIgPC0gcmVhZF9kZWxpbShvY3QxX2NvdW50c18xU003M19UMF9SMl9maWxlLCBjb2xfc2VsZWN0ID0gITEpCm9jdDFfY291bnRzXzFTTTczX1QwX1IzIDwtIHJlYWRfZGVsaW0ob2N0MV9jb3VudHNfMVNNNzNfVDBfUjNfZmlsZSwgY29sX3NlbGVjdCA9ICExKQoKb2N0MV9zY29yZXNfY291bnRzIDwtIGZ1bGxfam9pbihvY3QxX2NvdW50c18xU003M19UMF9SMSwgb2N0MV9jb21iaW5lZF9zY29yZXMpCmBgYAoKYGBge3J9CnNjb3JlX2Jhc2VsaW5lX3Bsb3RfYWJ1bmRhbmNlIDwtIGdncGxvdChvY3QxX3Njb3Jlc19jb3VudHMgJT4lIGZpbHRlcihtdXRhdGlvbl90eXBlICE9ICJYIiksCiAgICAgICAgICAgICAgICAgICAgIGFlcyh5ID0gY291bnQsIHggPSBHRlBfc2NvcmUpKSArCiAgZ2d0aXRsZSgnQmFzZWxpbmUgbGlicmFyeSBjb3VudCBhbmQgYWJ1bmRhbmNlIHNjb3JlIGNvcnJlbGF0aW9uJykgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjIpICsKICBzdGF0X2NvcihtZXRob2QgPSAic3BlYXJtYW4iLCBjb2xvciA9ICdibGFjaycsIGNvci5jb2VmLm5hbWUgPSAicmhvIikgKwogIGdlb21fc21vb3RoKG1ldGhvZD0nbG0nLCBzZSA9IFRSVUUpICsKICB5bGFiKCJCYXNlbGluZSBjb3VudCIpICsKICB4bGFiKCJBYnVuZGFuY2Ugc2NvcmUiKSArCiAgdGhlbWVfY2xhc3NpYygpIAoKc2NvcmVfYmFzZWxpbmVfcGxvdF9hYnVuZGFuY2UKCmdnc2F2ZSgib3V0cHV0L3Njb3JlX2Jhc2VsaW5lX3Bsb3RfYWJ1bmRhbmNlLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gNCwgc2NvcmVfYmFzZWxpbmVfcGxvdF9hYnVuZGFuY2UpCmdnc2F2ZSgib3V0cHV0L3Njb3JlX2Jhc2VsaW5lX3Bsb3RfYWJ1bmRhbmNlLnBkZiIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gNCwgc2NvcmVfYmFzZWxpbmVfcGxvdF9hYnVuZGFuY2UpCgoKc2NvcmVfYmFzZWxpbmVfcGxvdF9zbTczIDwtIGdncGxvdChvY3QxX3Njb3Jlc19jb3VudHMgJT4lIGZpbHRlcihtdXRhdGlvbl90eXBlICE9ICJYIiksCiAgICAgICAgICAgICAgICAgICAgIGFlcyh5ID0gY291bnQsIHggPSBTTTczXzFfc2NvcmUpKSArCiAgZ2d0aXRsZSgnQmFzZWxpbmUgbGlicmFyeSBjb3VudCBhbmQgZnVuY3Rpb24gc2NvcmUgY29ycmVsYXRpb24nKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMikgKwogIHN0YXRfY29yKG1ldGhvZCA9ICJzcGVhcm1hbiIsIGNvbG9yID0gJ2JsYWNrJywgY29yLmNvZWYubmFtZSA9ICJyaG8iKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kPSdsbScsIHNlID0gVFJVRSkgKwogIHlsYWIoIkJhc2VsaW5lIGNvdW50IikgKwogIHhsYWIoIkFidW5kYW5jZSBzY29yZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgCgpzY29yZV9iYXNlbGluZV9wbG90X3NtNzMKCmdnc2F2ZSgib3V0cHV0L3Njb3JlX2Jhc2VsaW5lX3Bsb3Rfc203My5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDQsIHNjb3JlX2Jhc2VsaW5lX3Bsb3Rfc203MykKZ2dzYXZlKCJvdXRwdXQvc2NvcmVfYmFzZWxpbmVfcGxvdF9zbTczLnBkZiIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gNCwgc2NvcmVfYmFzZWxpbmVfcGxvdF9zbTczKQoKc2NvcmVfYmFzZWxpbmVfcGxvdHMgPC0gc2NvcmVfYmFzZWxpbmVfcGxvdF9hYnVuZGFuY2UgKyBzY29yZV9iYXNlbGluZV9wbG90X3NtNzMgKyAKICAgICAgICAgICAgICAgICAgICBwbG90X2xheW91dChuY29sID0gMiwgbnJvdyA9IDEsIHdpZHRocyA9IGMoNSwgNSksIGhlaWdodHMgPSBjKDQpKQoKc2NvcmVfYmFzZWxpbmVfcGxvdHMKCmdnc2F2ZSgib3V0cHV0L3Njb3JlX2Jhc2VsaW5lX3Bsb3RzLnBuZyIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNCwgc2NvcmVfYmFzZWxpbmVfcGxvdHMpCmdnc2F2ZSgib3V0cHV0L3Njb3JlX2Jhc2VsaW5lX3Bsb3RzLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gNCwgc2NvcmVfYmFzZWxpbmVfcGxvdHMpCgoKYGBgCgpgYGB7cn0KCnZvbGNhbm9fR0ZQIDwtIGdncGxvdChvY3QxX2NvbWJpbmVkX3Njb3JlcyAlPiUgZmlsdGVyKG11dGF0aW9uX3R5cGUgIT0gIlgiKSwKICAgICAgICAgICAgICAgICAgICAgYWVzKHkgPSBHRlBfU0UsIHggPSBHRlBfc2NvcmUpKSArCiAgZ2d0aXRsZSgnQmFzZWxpbmUgbGlicmFyeSBjb3VudCBhbmQgZnVuY3Rpb24gc2NvcmUgY29ycmVsYXRpb24nKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMikgKwogIHlsYWIoIkFidW5kYW5jZSBTRSIpICsKICB4bGFiKCJBYnVuZGFuY2Ugc2NvcmUiKSArCiAgdGhlbWVfY2xhc3NpYygpIAoKdm9sY2Fub19HRlAKCnZvbGNhbm9fU003MyA8LSBnZ3Bsb3Qob2N0MV9jb21iaW5lZF9zY29yZXMgJT4lIGZpbHRlcihtdXRhdGlvbl90eXBlICE9ICJYIiksCiAgICAgICAgICAgICAgICAgICAgIGFlcyh5ID0gU003M18xX1NFLCB4ID0gU003M18xX3Njb3JlKSkgKwogIGdndGl0bGUoJ0Jhc2VsaW5lIGxpYnJhcnkgY291bnQgYW5kIGZ1bmN0aW9uIHNjb3JlIGNvcnJlbGF0aW9uJykgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjIpICsKICB5bGFiKCJGdW5jdGlvbiBTRSIpICsKICB4bGFiKCJGdW5jdGlvbiBzY29yZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgCgp2b2xjYW5vX1NNNzMKCmBgYAoKYGBge3J9Cm9jdDFfQUZfbWlzc2Vuc2VfZmlsZSA9Ii4uL2RhdGEvQWxwaGFNaXNzZW5zZV9hYV9zdWJzdGl0dXRpb25zX08xNTI0NS50c3YiCm9jdDFfQUZfbWlzc2Vuc2UgPC0gcmVhZF9kZWxpbShvY3QxX0FGX21pc3NlbnNlX2ZpbGUsIGRlbGltID0gJ1x0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbF9uYW1lcyA9IGMoJ3VuaXByb3RfaWQnLCAncHJvdGVpbl92YXJpYW50JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2FtX3BhdGhvZ2VuaWNpdHknLCAnYW1fY2xhc3MnKSkgJT4lCiAgbXV0YXRlKHByb3RlaW5fdmFyaWFudCA9IHBhc3RlKCdwLignLCBwcm90ZWluX3ZhcmlhbnQsICcpJywgc2VwID0gJycpKQoKb2N0MV9BRl9taXNzZW5zZSA8LSBvY3QxX0FGX21pc3NlbnNlICU+JSBtdXRhdGUocG9zID0gYXMubnVtZXJpYyhzdHJfbWF0Y2gocHJvdGVpbl92YXJpYW50LCAiXnAuXFwoW0EtWl0oWzAtOV0rKVtkQS1aX11cXCkiKVssMl0pKQoKCm9jdDFfQUZfbWlzc2Vuc2Vfc2NvcmVzIDwtIGZ1bGxfam9pbihvY3QxX0FGX21pc3NlbnNlLCBvY3QxX3Njb3JlcywgYnkgPSBjKCJwcm90ZWluX3ZhcmlhbnQiID0gImhndnMiKSkKCm9jdDFfQUZfbWlzc2Vuc2Vfc2NvcmVzIDwtIG9jdDFfQUZfbWlzc2Vuc2Vfc2NvcmVzICU+JSBtdXRhdGUocG9zID0gYXMubnVtZXJpYyhzdHJfbWF0Y2gocHJvdGVpbl92YXJpYW50LCAiXnAuXFwoW0EtWl0oWzAtOV0rKVtkQS1aX11cXCkiKVssMl0pKQoKb2N0MV9BRl9taXNzZW5zZV9zY29yZXMgPC0gb2N0MV9BRl9taXNzZW5zZV9zY29yZXMgJT4lIG11dGF0ZSh2YXJpYW50cyA9IHN0cl9tYXRjaChwcm90ZWluX3ZhcmlhbnQsICJecC5cXChbQS1aXVswLTldKyhbZEEtWl9dKVxcKSIpWywyXSkKCgoKYGBgCgpgYGB7cn0KCkFGX2NvcnJlbGF0aW9uIDwtIGdncGxvdChvY3QxX0FGX21pc3NlbnNlX3Njb3JlcyAlPiUgZmlsdGVyKG11dGF0aW9uX3R5cGUgIT0gIlgiKSwKICAgICAgICAgICAgICAgICAgICAgYWVzKHkgPSBhbV9wYXRob2dlbmljaXR5LCB4ID0gU003M18xX3Njb3JlKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjEsIGNvbG9yID0gJ2JsdWUnKSArCiAgeWxhYigiQWxwaGFNaXNzZW5zZSBwYXRob2dlbmljaXR5IHNjb3JlIikgKwogIHhsYWIoIkN5dG90b3hpY2l0eSBzY29yZSIpICsKICBzdGF0X2NvcihtZXRob2QgPSAic3BlYXJtYW4iLCBsYWJlbC54ID0gMSwgbGFiZWwueSA9IDAuMSwgY29sb3IgPSAnYmxhY2snLAogICAgICAgICAgIGNvci5jb2VmLm5hbWUgPSAicmhvIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuMzQsIGxpbmV0eXBlID0gMikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjU2NCwgbGluZXR5cGUgPSAyKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuNjc5ODA3NSwgbGluZXR5cGUgPSAyKSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IC0wLjgzNzY5MzYsIGxpbmV0eXBlID0gMikgKyAKICB0aGVtZV9jbGFzc2ljKCkgCgpBRl9jb3JyZWxhdGlvbgoKZ2dzYXZlKCJvdXRwdXQvQUZfY29ycmVsYXRpb25fc203My5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDIsIEFGX2NvcnJlbGF0aW9uKQoKCkFGX2NvcnJlbGF0aW9uX0dGUCA8LSBnZ3Bsb3Qob2N0MV9BRl9taXNzZW5zZV9zY29yZXMgJT4lIGZpbHRlcihtdXRhdGlvbl90eXBlICE9ICJYIiksCiAgICAgICAgICAgICAgICAgICAgIGFlcyh5ID0gYW1fcGF0aG9nZW5pY2l0eSwgeCA9IEdGUF9zY29yZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4xLCBjb2xvciA9ICdyZWQnKSArCiAgeWxhYigiQWxwaGFNaXNzZW5zZSBwYXRob2dlbmljaXR5IHNjb3JlIikgKwogIHhsYWIoIkFidW5kYW5jZSBzY29yZSIpICsKICBzdGF0X2NvcihtZXRob2QgPSAic3BlYXJtYW4iLCBsYWJlbC54ID0gLTUsIGxhYmVsLnkgPSAwLjEsIGNvbG9yID0gJ2JsYWNrJywKICAgICAgICAgICBjb3IuY29lZi5uYW1lID0gInJobyIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLjM0LCBsaW5ldHlwZSA9IDIpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC41NjQsIGxpbmV0eXBlID0gMikgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLjc5Njc2OTEsIGxpbmV0eXBlID0gMikgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAtMC43MjA3MzIxLCBsaW5ldHlwZSA9IDIpICsgCiAgdGhlbWVfY2xhc3NpYygpIAoKQUZfY29ycmVsYXRpb25fR0ZQCgpnZ3NhdmUoIm91dHB1dC9BRl9jb3JyZWxhdGlvbl9HRlAucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSAyLCBBRl9jb3JyZWxhdGlvbl9HRlApCgoKZm9sZGluZ19wbG90cyA8LSBBRl9jb3JyZWxhdGlvbiArIEFGX2NvcnJlbGF0aW9uX0dGUCArIAogICAgICAgICAgICAgICAgICAgIHBsb3RfbGF5b3V0KG5jb2wgPSAyLCBucm93ID0gMSwgd2lkdGhzID0gYyg1LCA1KSwgaGVpZ2h0cyA9IGMoMikpCgpmb2xkaW5nX3Bsb3RzCgpnZ3NhdmUoIm91dHB1dC9BRl9jb3JyZWxhdGlvbl9wbG90cy5wbmciLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA0LCBmb2xkaW5nX3Bsb3RzKQpnZ3NhdmUoIm91dHB1dC9BRl9jb3JyZWxhdGlvbl9wbG90cy5wZGYiLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA0LCBmb2xkaW5nX3Bsb3RzKQoKCgpgYGAKCmBgYHtyfQoKb3JkZXIgPC0gYygnRF8xJywgJ0gnLCAnSycsICdSJywgJ0QnLCAnRScsCiAgICAgICAgICAnQycsICdNJywgJ04nLCAnUScsICdTJywgJ1QnLCAnQScsICdJJywgJ0wnLCAnVicsICdXJywgJ0YnLAogICAgICAgICAgJ1knLCAnRycsICdQJykKCm5hbWVzIDwtIGMoJ0RlbCcsICdIJywgJ0snLCAnUicsICdEJywgJ0UnLAogICAgICAgICAgJ0MnLCAnTScsICdOJywgJ1EnLCAnUycsICdUJywgJ0EnLCAnSScsICdMJywgJ1YnLCAnVycsICdGJywKICAgICAgICAgICdZJywgJ0cnLCAnUCcpCgpvY3QxX3d0ID0gIk1QVFZERElMRVFWR0VTR1dGUUtRQUZMSUxDTExTQUFGQVBJQ1ZHSVZGTEdGVFBESEhDUVNQR1ZBRUxTUVJDR1dTUEFFRUxOWVRWUEdMR1BBR0VBRkxHUUNSUllFVkRXTlFTQUxTQ1ZEUExBU0xBVE5SU0hMUExHUENRREdXVllEVFBHU1NJVlRFRk5MVkNBRFNXS0xETEZRU0NMTkFHRkxGR1NMR1ZHWUZBRFJGR1JLTENMTEdUVkxWTkFWU0dWTE1BRlNQTllNU01MTEZSTExRR0xWU0tHTldNQUdZVExJVEVGVkdTR1NSUlRWQUlNWVFNQUZUVkdMVkFMVEdMQVlBTFBIV1JXTFFMQVZTTFBURkxGTExZWVdDVlBFU1BSV0xMU1FLUk5URUFJS0lNREhJQVFLTkdLTFBQQURMS01MU0xFRURWVEVLTFNQU0ZBRExGUlRQUkxSS1JURklMTVlMV0ZURFNWTFlRR0xJTEhNR0FUU0dOTFlMREZMWVNBTFZFSVBHQUZJQUxJVElEUlZHUklZUE1BTVNOTExBR0FBQ0xWTUlGSVNQRExIV0xOSUlJTUNWR1JNR0lUSUFJUU1JQ0xWTkFFTFlQVEZWUk5MR1ZNVkNTU0xDRElHR0lJVFBGSVZGUkxSRVZXUUFMUExJTEZBVkxHTExBQUdWVExMTFBFVEtHVkFMUEVUTUtEQUVOTEdSS0FLUEtFTlRJWUxLVlFUU0VQU0dUIgoKcHJpbnRfaGVhdG1hcChvY3QxX2NvbWJpbmVkX3Njb3JlcywgR0ZQX3Njb3JlLCBvY3QxX3d0KQoKYGBgCgoKYGBge3J9Cgp2YXJpYW5jZV9wbG90IDwtIGdncGxvdChkYXRhID0gb2N0MV9BRl9taXNzZW5zZSAlPiUgZ3JvdXBfYnkocG9zKSAlPiUKICAgIHN1bW1hcmlzZShjdiA9IHNkKGFtX3BhdGhvZ2VuaWNpdHksIG5hLnJtPVQpL2FicyhtZWFuKGFtX3BhdGhvZ2VuaWNpdHksIG5hLnJtPVQpKSksIGFlcyh4ID0gY3YpKSArCiAgZ2VvbV9kZW5zaXR5KCkgKwogIGdlb21fZGVuc2l0eShkYXRhID0gb2N0MV9jb21iaW5lZF9zY29yZXMgJT4lIGdyb3VwX2J5KHBvcykgJT4lCiAgICBzdW1tYXJpc2UoY3YgPSBzZChTTTczXzFfc2NvcmUsIG5hLnJtPVQpL2FicyhtZWFuKFNNNzNfMV9zY29yZSwgbmEucm09VCkpKSwgYWVzKHggPSBjdiksIGNvbG9yID0gImJsdWUiLCBsaW5ldHlwZSA9IDIpICsKICBnZW9tX2RlbnNpdHkoZGF0YSA9IG9jdDFfY29tYmluZWRfc2NvcmVzICU+JSBncm91cF9ieShwb3MpICU+JQogICAgc3VtbWFyaXNlKGN2ID0gc2QoR0ZQX3Njb3JlLCBuYS5ybT1UKS9hYnMobWVhbihHRlBfc2NvcmUsIG5hLnJtPVQpKSksIGFlcyh4ID0gY3YpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9IDIpICsKICB4bGltKGMoMCwgMTApKSArCiAgeWxhYigiRGVuc2l0eSIpICsKICB4bGFiKCJDb2VmZmljaWVudCBvZiB2YXJpYXRpb24iKSArCiAgdGhlbWVfY2xhc3NpYygpCgp2YXJpYW5jZV9wbG90CgpnZ3NhdmUoIm91dHB1dC9BRl9DVl9wbG90LnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDUsIHZhcmlhbmNlX3Bsb3QpCmdnc2F2ZSgib3V0cHV0L0FGX0NWX3Bsb3QucGRmIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNSwgdmFyaWFuY2VfcGxvdCkKCgpgYGAKCgpXcml0ZSB0aGUgc2NvcmVzIGFzIDMgbGV0dGVyIEhHVlMgQUFzIHRvIHN1Ym1pdCB0byBNQVZFIGRiCmBgYHtyfQoKd3JpdGUuY3N2KG9jdDFfY29tYmluZWRfc2NvcmVzICU+JSB1bmdyb3VwKCkgJT4lIHJvd3dpc2UoKSAlPiUgbXV0YXRlKGhndnNfMyA9IGNvbnZlcnRfMUFBX2hndnMoaGd2cykpLCAiLi4vZGF0YS9NQVZFX2RiX3Njb3Jlcy5jc3YiKQoKYGBgCgpgYGB7cn0KCmBgYAoKCmBgYA==